package net.guerlab.smart.qcloud.im.client;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import net.guerlab.smart.qcloud.im.*;
import net.guerlab.smart.qcloud.im.utils.UserSigUtils;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 抽象Im客户端
 *
 * @author guer
 */
@AllArgsConstructor
public abstract class AbstractImClient implements ImClient {

    private static final String QUESTION_MARK = "?";

    private static final String EQUALS_MARK = "=";

    private static final String AND_MARK = "&";

    /**
     * objectMapper
     */
    protected ObjectMapper objectMapper;

    /**
     * appKey
     */
    private Long sdkAppId;

    private String key;

    /**
     * 用户名，调用 REST API 时必须为 App 管理员帐号
     */
    private String identifier;

    @Override
    public final <R extends AbstractImResponse> R getResponse(AbstractImRequest<R> request) {
        Map<String, Object> query = new LinkedHashMap<>(request.query());

        query.put(ImConstants.PARAMS_SDK_APP_ID, sdkAppId);
        query.put(ImConstants.PARAMS_IDENTIFIER, identifier);
        query.put(ImConstants.PARAMS_RANDOM, ThreadLocalRandom.current().nextInt());
        query.put(ImConstants.PARAMS_CONTENT_TYPE, ImConstants.CONTENT_TYPE_JSON);
        try {
            query.put(ImConstants.PARAMS_USERSIG,
                    UserSigUtils.genSig(sdkAppId, key, identifier, ImConstants.DEFAULT_EXPIRE));
        } catch (Exception e) {
            throw new ImException(e.getLocalizedMessage(), e);
        }

        StringBuilder queryBuilder = new StringBuilder();

        for (Map.Entry<String, Object> entry : query.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            queryBuilder.append(key);
            queryBuilder.append(EQUALS_MARK);
            queryBuilder.append(value);
            queryBuilder.append(AND_MARK);
        }

        StringBuilder uriBuilder = new StringBuilder(ImConstants.BASE_URL);
        uriBuilder.append(request.uri());

        if (uriBuilder.indexOf(QUESTION_MARK) == -1) {
            uriBuilder.append(QUESTION_MARK);
        } else {
            uriBuilder.append(AND_MARK);
        }
        uriBuilder.append(queryBuilder);

        return executeWithHttpRequest(request, uriBuilder.toString(), objectMapper);
    }

    /**
     * 执行http请求
     *
     * @param request
     *         业务请求对象
     * @param uri
     *         url
     * @param objectMapper
     *         objectMapper
     * @param <T>
     *         响应类型
     * @return 响应
     */
    protected abstract <T extends AbstractImResponse> T executeWithHttpRequest(AbstractImRequest<T> request, String uri,
            ObjectMapper objectMapper);
}
